#include "library/test_tool/memory_leak.h"
#include "library/unit_test/unit_test.h"
#include "library/base/string.h"

using namespace Base;

void TestStringConstructor()
{
	ASSERT(WString() == L"" , L"StringBase()");

	ASSERT(WString(WString()) == L"", L"StringBase(const StringBase<_Type>& Object)");
	ASSERT(WString(WString(L"test")) == L"test", L"StringBase(const StringBase<_Type>& Object)");

	ASSERT(WString((const wchar_t*)0) == L"", L"StringBase(const _Type* Object)");
	ASSERT(WString(L"test") == L"test", L"StringBase(const _Type* Object)");

	ASSERT(WString((const wchar_t*)0, 1) == L"", L"StringBase(const _Type* Object, const int Count)");
	ASSERT(WString(L"testtest", 4) == L"test", L"StringBase(const _Type* Object, const int Count)");
	ASSERT(WString(L"test", 8) == L"test", L"StringBase(const _Type* Object, const int Count)");

	ASSERT(WString(L'a') == L"a", L"StringBase(const _Type Object)");
}

void TestStringOperatorAt()
{
    try
	{
		ASSERT(WString()[-1] == L'', L"operator[]");
	}
	catch (Exception e)
	{
		ASSERT(e == exceptionINDEX_OUT_OF_RANGE, L"operator[]");
	}
	try
	{
		ASSERT(WString()[0] == L'', L"operator[]");
	}
	catch (Exception e)
	{
		ASSERT(e == exceptionINDEX_OUT_OF_RANGE, L"operator[]");
	}
	ASSERT(WString(L"a")[0] == L'a', L"operator[]");
	ASSERT(WString(L"test")[0] == L't', L"operator[]");
	ASSERT(WString(L"test")[1] == L'e', L"operator[]");
	ASSERT(WString(L"test")[2] == L's', L"operator[]");
	ASSERT(WString(L"test")[3] == L't', L"operator[]");

	WString str(L"testa");
	str[4] = L'b';
	ASSERT(str == L"testb", L"operator[]");
}

void TestStringOperatorAssign()
{
	WString str1;
	WString str2(L"test");
	ASSERT(str1 == L"", L"operator=");
	str1 = str2;
	ASSERT(str1 == L"test", L"operator=");
	str1 = L"";
	ASSERT(str1 == L"", L"operator=");
	str1 = str2;
	ASSERT(str1 == L"test", L"operator=");

	WString str;
	str += (const wchar_t*)0;
	ASSERT(str == L"", L"operator+=");
	str += L"";
	ASSERT(str == L"", L"operator+=");
	str += L"test";
	ASSERT(str == L"test", L"operator+=");
}

void TestStringOperatorAdd()
{
	ASSERT(WString() + L"" == L"", L"operator+");
	ASSERT(L"" + WString() == L"", L"operator+");
	ASSERT(WString() + WString() == L"", L"operator+");
	ASSERT(WString(L"te") + L"st" == L"test", L"operator+");
	ASSERT(L"te" + WString(L"st") == L"test", L"operator+");
	ASSERT(WString(L"te") + WString(L"st") == L"test", L"operator+");
}

void TestStringOperatorCompare()
{
	ASSERT(WString() < L"test", L"operator<");
	ASSERT(L"" < WString(L"test"), L"operator<");
	ASSERT(WString() < WString(L"test"), L"operator<");

	ASSERT(WString() <= L"", L"operator<=");
	ASSERT(L"" <= WString(), L"operator<=");
	ASSERT(WString() <= WString(), L"operator<=");
	ASSERT(WString() <= L"test", L"operator<=");
	ASSERT(L"" <= WString(L"test"), L"operator<=");
	ASSERT(WString() <= WString(L"test"), L"operator<=");

	ASSERT(WString(L"test") > L"", L"operator>");
	ASSERT(L"test" > WString(), L"operator>");
	ASSERT(WString(L"test") > WString(), L"operator>");

	ASSERT(WString() >= L"", L"operator>=");
	ASSERT(L"" >= WString(), L"operator>=");
	ASSERT(WString() >= WString(), L"operator>=");
	ASSERT(WString(L"test") >= L"", L"operator>=");
	ASSERT(L"test" >= WString(), L"operator>=");
	ASSERT(WString(L"test") >= WString(), L"operator>=");

	ASSERT(WString() == L"", L"operator==");
	ASSERT(L"" == WString(), L"operator==");
	ASSERT(WString() == WString(), L"operator==");
	ASSERT(WString(L"test") == L"test", L"operator==");
	ASSERT(L"test" == WString(L"test"), L"operator==");
	ASSERT(WString(L"test") == WString(L"test"), L"operator==");

	ASSERT(WString() != L"test", L"operator!=");
	ASSERT(L"" != WString(L"test"), L"operator!=");
	ASSERT(WString() != WString(L"test"), L"operator!=");
}

void TestStringGetLength()
{
	ASSERT(WString().GetLength() == 0, L"GetLength");
	ASSERT(WString(L"a").GetLength() == 1, L"GetLength");
	ASSERT(WString(L"test").GetLength() == 4, L"GetLength");
}

void TestStringIndexOf()
{
	ASSERT(WString().IndexOf(L"") == -1, L"IndexOf");
	ASSERT(WString().IndexOf(L"test") == -1, L"IndexOf");
	ASSERT(WString(L"test").IndexOf(L"") == 0, L"IndexOf");
	ASSERT(WString(L"test").IndexOf(L"test") == 0, L"IndexOf");
	ASSERT(WString(L"test").IndexOf(L"abcd") == -1, L"IndexOf");
	ASSERT(WString(L"testabc").IndexOf(L"test") == 0, L"IndexOf");
	ASSERT(WString(L"test").IndexOf(L"testabc") == -1, L"IndexOf");
	ASSERT(WString(L"testabc").IndexOf(L"ab") == 4, L"IndexOf");
}

void TestStringLastIndexOf()
{
	ASSERT(WString().LastIndexOf(L"") == -1, L"NULL.LastIndexOf(NULL)");
	ASSERT(WString().LastIndexOf(L"test") == -1, L"NULL.LastIndexOf(test)");
	ASSERT(WString(L"test").LastIndexOf(L"") == 3, L"test.LastIndexOf(NULL)");
	ASSERT(WString(L"test").LastIndexOf(L"test") == 0, L"test.LastIndexOf(test)");
	ASSERT(WString(L"test").LastIndexOf(L"abcd") == -1, L"test.LastIndexOf(abcd)");
	ASSERT(WString(L"testabc").LastIndexOf(L"test") == 0, L"testabc.LastIndexOf(test)");
	ASSERT(WString(L"test").LastIndexOf(L"testabc") == -1, L"test.LastIndexOf(testabc)");
	ASSERT(WString(L"testabc").LastIndexOf(L"ab") == 4, L"testabc.LastIndexOf(ab)");
	ASSERT(WString(L"abctestabc").LastIndexOf(L"ab") == 7, L"abctestabc.LastIndexOf(ab)");
}

TESTCASE(String)
{
	TestStringConstructor();
	TestStringOperatorAt();
	TestStringOperatorAssign();
	TestStringOperatorAdd();
	TestStringOperatorCompare();
	TestStringGetLength();
	TestStringIndexOf();
	TestStringLastIndexOf();
}